#ifndef SERVERSYNCH_H
#define SERVERSYNCH_H

#include "copyright.h"
#include "list.h"
#include "system.h"
#include "server.h"

class Server;

class ServerLock {
  public:
    ServerLock(char* debugName, int lockIndex, Server* serv);  		// initialize lock to be FREE
    ~ServerLock();				// deallocate lock
    char* getName() { return name; }	// debugging assist

    void SAcquire(int userProgID); // these are the only operations on a lock
    void SRelease(int userProgID, bool isWait); // they are both *atomic*
	void SCreateLock();

    bool SIsHeldByCurrentThread(int userProgID);	// true if the current thread
					// holds this lock.  Useful for
					// checking in Release, and in
					// Condition variable ops below.
					
	int getLockID();

  private:
    char* name;				// for debugging
	bool busy;              // if the lock is busy or free (true = busy)
	bool created;
	int ownerThread;    // Current thread that owns the lock;
	List* waitingQueue;       		// queue of threads waiting to acquire the lock
	int lockID;
	Server* server;
    // plus some other stuff you'll need to define
};

class ServerCondition {
  public:
    ServerCondition(char* debugName, int condIndex, Server* serv);		// initialize condition to 
					// "no one waiting"
    ~ServerCondition();			// deallocate the condition
    char* getName() { return (name); }
    
    void SWait(ServerLock *ServCondLock, int userProgID); 	// these are the 3 operations on 
					// condition variables; releasing the 
					// lock and going to sleep are 
					// *atomic* in Wait()
    void SSignal(ServerLock *ServCondLock, int userProgID);   // ServCondLock must be held by
    void SBroadcast(ServerLock *ServCondLock, int userProgID);// the currentThread for all of 
					// these operations

  private:
    char* name;
	ServerLock* waitingLock;              // current waiting lock
	List* waitingQueue;       		// queue of threads waiting to acquire the lock
	int condID;
	Server* server;
    // plus some other stuff you'll need to define
};

#endif

